#include "RoomManager.h"
#include "Signaling.h"
#include "PublicFunHelper.h"
#include "JanusPeerConnection.h"
#include "RemoteMediaStream.h"
#include "LocalMediaStream.h"
#include "rtc_base/win32_socket_init.h"
#include "rtc_base/win32_socket_server.h"
#include "rtc_base/ssl_adapter.h"

RoomManager::RoomManager(QObject *parent) : QObject(parent)
{
    rtc::WinsockInitializer winsock_init;
    rtc::Win32SocketServer *w32_ss = new rtc::Win32SocketServer();
    rtc::Win32Thread *w32_thread = new rtc::Win32Thread(w32_ss);
    rtc::ThreadManager::Instance()->SetCurrentThread(w32_thread);
    rtc::InitializeSSL();

    m_peerList.clear();
    m_strOpaqueID.clear();
    m_seesionID = 0;
    m_privateID = 0;
    m_pSignalHelper = NULL;
}

RoomManager::~RoomManager()
{
    rtc::CleanupSSL();
}

void RoomManager::init()
{
    m_pSignalHelper = new Signaling(this);
    bool bOk = connect(m_pSignalHelper, &Signaling::sigConnected,
                  this, &RoomManager::slotConnected);
    Q_ASSERT(bOk);

    m_pSignalHelper->setEventCallBack("joined", std::bind(&RoomManager::onEventJoin, this, std::placeholders::_1));
    m_pSignalHelper->setEventCallBack("event", std::bind(&RoomManager::onEventEvent, this, std::placeholders::_1));
    m_pSignalHelper->setEventCallBack("attached", std::bind(&RoomManager::ontEventAttached, this, std::placeholders::_1));

    m_strOpaqueID = QString("videoroomtest-") + PublicFunHelper::getRandomString(12);
}

void RoomManager::connectToServer(const QString &strUrl)
{
    m_pSignalHelper->connectToServer(strUrl);
}

void RoomManager::slotConnected()
{
    createSessionID();
}

void RoomManager::createSessionID()
{
    QJsonObject msg;
    msg[KEY_JANUS] = "create";
    m_pSignalHelper->sendMsg(msg, std::bind(&RoomManager::onCreateSessionID, this, std::placeholders::_1));
}

void RoomManager::onCreateSessionID(const QJsonObject &recvData)
{
    if(recvData.contains("id"))
    {
        m_seesionID = recvData.value("id").toDouble();
        m_pSignalHelper->setSeeionID(m_seesionID);
    }

    JanusPeerConnection *pPeer = new JanusPeerConnection(m_pSignalHelper, m_strOpaqueID, this);
    m_peerList.append(pPeer);
    pPeer->attachVideoRoom();
}

void RoomManager::onEventJoin(const QJsonObject &recvData)
{
    Q_UNUSED(recvData);
    qDebug() << __func__ << recvData;


    LocalMediaStream *pStream = LocalMediaStream::getInstance();
    pStream->init();

    QJsonObject jsonPluginData = recvData.value("plugindata").toObject();
    QJsonObject jsonData = jsonPluginData.value("data").toObject();
    m_privateID = jsonData.value("private_id").toDouble();
    qint64 sender = recvData.value("sender").toDouble(); // peer id
    for (JanusPeerConnection *peer : m_peerList)
    {
        // 判断peerid是否相等
        if (peer->getHandleID() == sender)
        {
            peerConnect(sender, peer);
            break;
        }
    }

    onEventPublish(recvData);
}

void RoomManager::onEventEvent(const QJsonObject &recvData)
{
    Q_UNUSED(recvData);
    qDebug() << __func__ << recvData;
}

void RoomManager::ontEventAttached(const QJsonObject &recvData)
{
    Q_UNUSED(recvData);
    qDebug() << __func__ << recvData;
}

void RoomManager::onEventPublish(const QJsonObject &recvData)
{
    QJsonObject jsonPluginData = recvData.value("plugindata").toObject();
    QJsonObject jsonData = jsonPluginData.value("data").toObject();
    QJsonArray publisherArray = jsonData.value("publishers").toArray();
    for(int i = 0; i < publisherArray.size(); i++)
    {
        QJsonObject onePublisher = publisherArray.at(i).toObject();
        if(!onePublisher.isEmpty())
        {
            qint64 id = onePublisher.value("id").toDouble();
            QString strDisplay = onePublisher.value("display").toString();
            if(id > 0)
            {
                JanusPeerConnection *pPeer = new JanusPeerConnection(m_pSignalHelper, m_strOpaqueID, this);
                m_peerList.append(pPeer);
                pPeer->setSubscribe(id);
                pPeer->setPrivateID(m_privateID);
                pPeer->attachVideoRoom();
            }
        }
    }
}

void RoomManager::onEventUnPublish(const QJsonObject &recvData)
{
    QJsonObject jsonPluginData = recvData.value("plugindata").toObject();
    QJsonObject jsonData = jsonPluginData.value("data").toObject();
    qint64 id = jsonData.value("unpublished").toDouble();
    if(id > 0)
    {
        for(int i = 0; i < m_peerList.size(); i++)
        {
            JanusPeerConnection *pItem = m_peerList.at(i);
            qint64 idSubscribe = pItem->getSubscribe();
            if(id == idSubscribe)
            {
                m_peerList.takeAt(i);
                break;
            }
        }
    }
}

void RoomManager::peerConnect(const qint64 &peerID, JanusPeerConnection *peer)
{
    rtc::scoped_refptr<RemoteMediaStream> remoteStream = new rtc::RefCountedObject<RemoteMediaStream>(peerID);
    remoteStream->setPeerConnection(peer);
    m_remoteStreamList.append(remoteStream);
    remoteStream->connectToPeer(true);
}

